home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * Spaced: The Three-D Space Editor
- *
- * spaced.c
- *
- * This file, along with it's include file, spaced.h, contains
- * all necessary routines for Spaced. See the comments in the include
- * file for instructions on hooking it up to your code.
- *
- * Howard Look
- * July, 1989
- *
- */
-
- #include <gl.h>
- #include <device.h>
- #include <math.h>
- #include "spaced.h"
-
- #define X 0
- #define Y 1
- #define Z 2
-
- #define XY 2
- #define XZ 1
- #define YZ 0
- #define NONE -1
- #define EDGE_PICKED 99
-
- /* Prototypes for internal functions */
- static void transform_point(
- Coord *,
- Matrix,
- Scoord *);
- static float find_distance(
- Scoord p[2],
- Scoord q[2],
- Scoord r[2]);
- static float cos_angle_between(
- Scoord center[2],
- Scoord p1[2],
- Scoord p2[2]);
- static float dist(
- Scoord p1[2],
- Scoord p2[2]);
- static void find_close(
- Scoord m[2],
- Scoord p[2],
- Scoord q[3][2][2],
- short a[2][2],
- int i[3][2],
- int);
- static int length(Scoord axis[2][2]);
- static Boolean colinear(Scoord axis1[2][2], Scoord axis2[2][2]);
-
-
- /* window information */
- static long origin_x, origin_y, size_x, size_y;
-
- /* Which plane is motion constrained to */
- static int plane;
- static int edge;
-
-
- static Coord initial_origin[3];
- static Scoord initial_screen_origin[2];
-
- static Boolean line_constrain, plane_constrain, first_time, constraint_ok;
-
- static int colinear_threshold = SP_COLINEAR_THRESHOLD;
- static int constraint_threshold = SP_CONSTRAINT_THRESHOLD;
-
- static Device line_but1 = SP_LINE_BUTTON1;
- static Device line_but2 = SP_LINE_BUTTON2;
-
- static Device plane_but1 = SP_PLANE_BUTTON1;
- static Device plane_but2 = SP_PLANE_BUTTON2;
-
-
-
- /*
- * Call this routine when you have completed all desired motion on a
- * given point.
- */
- void end_spaced(void)
- {
- /* A gratuitous function for future expansion */
- }
-
-
- /*
- * Call this routine to change any of spaced's parameters from or to
- * their default values. Calling with any parameter == -1 will reset
- * that parameter to its default value.
- *
- * See the file spaced.h for a description of parameters and their
- * default values.
- */
- void set_spaced(
- int col_thresh,
- int const_thresh,
- Device line1,
- Device line2,
- Device plane1,
- Device plane2)
- {
- if (col_thresh == SP_DEFAULT)
- colinear_threshold = SP_COLINEAR_THRESHOLD;
- else
- colinear_threshold = col_thresh;
-
- if (const_thresh == SP_DEFAULT)
- constraint_threshold = SP_CONSTRAINT_THRESHOLD;
- else
- constraint_threshold = const_thresh;
-
- if (line1 == SP_DEFAULT)
- line_but1 = SP_LINE_BUTTON1;
- else
- line_but1 = line1;
-
- if (line2 == SP_DEFAULT)
- line_but1 = SP_LINE_BUTTON1;
- else
- line_but1 = line2;
-
- if (plane1 == SP_DEFAULT)
- plane_but1 = SP_PLANE_BUTTON1;
- else
- plane_but1 = plane1;
-
- if (plane2 == SP_DEFAULT)
- plane_but1 = SP_PLANE_BUTTON2;
- else
- plane_but1 = plane2;
-
- }
-
-
-
- void start_spaced()
- {
- plane = NONE;
- edge = NONE;
- first_time = TRUE;
- constraint_ok = FALSE;
- }
-
- static Matrix idmat=
- {
- 1., 0., 0., 0.,
- 0., 1., 0., 0.,
- 0., 0., 1., 0.,
- 0., 0., 0., 1.,
- };
-
- /*
- * The main routine. This is what you call to do update the position
- * of a three-d point in world space.
- *
- * M is the matrix that gets your point from its world space into screen
- * space. If you are in single matrix mode, just do a getmatrix and pass
- * it here. If you are in double matrix mode, you will need to multiply
- * the viewing matrix by the projection matrix to get the matrix needed here.
- *
- * origin is the coordinates of the point you wish to move. This routine
- * will modify origin.
- *
- * limits specifies the bounding box that you wish origin to be contained
- * within. It's format is limit[x=0, y=1, z=2][lo=0, hi=1]
- *
- * See the comments in spaced.h for more implementation information.
- */
- int spaced(Matrix M, Coord origin[3], Coord limit[3][2])
- {
- /**************
- * Declarations
- **************/
-
-
- /*
- * Remember what mmode() the program is in; must save projection
- * matrix if not MSINGLE
- */
- int old_mmode;
-
- /* Temporary matrix to squirrel away the projection matrix */
- Matrix old_projection;
-
- /* endpoint of line in world space projected from mouse pos'n */
- Coord p1[3],p2[3];
-
- /* dummy view object used to find that line using mapw */
- static Object vobj;
-
- /* Dont want to waste time and memory recreating that object */
- static Boolean object_created = FALSE;
-
- /* Mouse pos'n */
- Scoord mouse[2];
-
- /* Screen coords of the point being moved */
- Scoord screen_motion_point[2];
-
- /* Which axes mouse is between[axis 0,1][endpoint 0,1] */
- static short between[2][2];
-
- /* Your basic first-year geometry stuff */
- Coord dx,dy,dz,x_slope,y_slope,z_slope,
- x_int,y_int,z_int,x_proj,x_proj2,y_proj,y_proj2,z_proj,z_proj2;
-
- /* Screen coords of the six axes endpoints
- screen_axis[x,y,z][end 0,1][x,y] */
- Scoord screen_axis[3][2][2];
-
- /* used in finding screen axes */
- Coord temp[3];
-
- /* Is the point inside of the bounding volume ? */
- Boolean within_bounds;
-
-
- /*
- * which axes to ignore when moving:
- * at corners, ignore 3 of them
- * at edges, ignore 2 of them
- * at wall, ignore 1 of them
- * inside, ignore none
- *
- * ignore[][0] = axis, ignore[1] = endpt */
- int ignore[3][2];
- int ignore_counter = 0;
-
- /* loop variables */
- int i,j;
-
- Scoord temp_axis[2][2];
-
- Boolean at_edge;
-
- /* constraint value to return */
- int constraint_return = SP_NONE;
-
- /***********************
- * Let the code begin...
- ***********************/
-
- /* The mouse be here */
- mouse[0] = getvaluator(MOUSEX);
- mouse[1] = getvaluator(MOUSEY);
-
- /* what the window is like */
- getorigin(&origin_x, &origin_y);
- getsize(&size_x, &size_y);
-
- old_mmode = getmmode();
- if (old_mmode != MSINGLE)
- {
- mmode(MPROJECTION);
- getmatrix(old_projection);
- loadmatrix(idmat);
- mmode(MSINGLE);
- }
-
- /* create the dummy view object, if necessary */
- if (! object_created)
- {
- vobj = genobj();
- makeobj(vobj); closeobj();
- object_created = TRUE;
- }
-
- /* use the current world->screen transformation */
- pushmatrix();
- delobj(vobj);
- makeobj(vobj);
- loadmatrix(M);
- closeobj();
- popmatrix();
-
- /* find the line that the mouse position maps to in world space */
- mapw(vobj, mouse[0]-origin_x, mouse[1]-origin_y,
- &p1[0], &p1[1], &p1[2], &p2[0], &p2[1], &p2[2]);
-
- /* find screen coords of the axes */
- for (i=0; i<3; i++)
- for (j=0; j<2; j++)
- {
- temp[0] = origin[0];
- temp[1] = origin[1];
- temp[2] = origin[2];
- temp[i] = limit[i][j];
- transform_point(temp, M, screen_axis[i][j]);
- }
-
- /* and of the point in motion */
- temp[0] = origin[0];
- temp[1] = origin[1];
- temp[2] = origin[2];
- transform_point(temp, M, screen_motion_point);
-
- /* Check if constraining starts/stops */
- plane_constrain = getbutton(plane_but1) || getbutton(plane_but2);
- line_constrain = getbutton(line_but1) || getbutton(line_but2);
-
- /* Line constraining is more constraining then plane constraining (!) */
- if (line_constrain)
- plane_constrain = FALSE;
-
- /* Only pick a plane once if constraining, every time if not */
- if ((! line_constrain) && (! plane_constrain))
- {
- plane = NONE;
- constraint_ok = FALSE;
- first_time = TRUE;
- }
-
- /* Setup initial constraint conditions */
- if ((line_constrain || plane_constrain) && first_time)
- {
- first_time = FALSE;
- plane = NONE;
-
- initial_screen_origin[0] = screen_motion_point[0];
- initial_screen_origin[1] = screen_motion_point[1];
-
- initial_origin[0] = origin[0];
- initial_origin[1] = origin[1];
- initial_origin[2] = origin[2];
- }
-
-
- /* Check boundary conditions
- * Only do this once if constraining
- */
- if (plane == NONE)
- {
- within_bounds = TRUE;
-
- ignore_counter = 0;
-
- for(i=0; i<3; i++)
- for(j=0; j<2; j++)
- if (origin[i] == limit[i][j])
- {
- within_bounds = FALSE;
- ignore[ignore_counter][0] = i;
- ignore[ignore_counter][1] = j;
- ignore_counter++;
- }
- }
- at_edge = (ignore_counter >= 2);
-
-
- /* Check if mouse has moved far enough to do constrained motion */
- if ((line_constrain || plane_constrain) &&
- (plane == NONE) &&
- (!constraint_ok))
- {
- temp_axis[0][0] = (Scoord)(mouse[0]);
- temp_axis[0][1] = (Scoord)(mouse[1]);
-
- temp_axis[1][0] = initial_screen_origin[0];
- temp_axis[1][1] = initial_screen_origin[1];
-
- constraint_ok = (length(temp_axis) > SP_CONSTRAINT_THRESHOLD);
- }
-
-
- /* Check for axis colinearity. Ignore shorter of two colinear axes */
- if ((within_bounds) && (plane == NONE))
- {
- if (colinear(screen_axis[0],screen_axis[1]))
- if (length(screen_axis[0]) < length(screen_axis[1]))
- {
- ignore[ignore_counter][0] = 0;
- ignore[ignore_counter][1] = 0;
- ignore_counter++;
- ignore[ignore_counter][0] = 0;
- ignore[ignore_counter][1] = 1;
- ignore_counter++;
- }
- else
- {
- ignore[ignore_counter][0] = 1;
- ignore[ignore_counter][1] = 0;
- ignore_counter++;
- ignore[ignore_counter][0] = 1;
- ignore[ignore_counter][1] = 1;
- ignore_counter++;
- }
- else if (colinear(screen_axis[0],screen_axis[2]))
- if (length(screen_axis[0]) < length(screen_axis[2]))
- {
- ignore[ignore_counter][0] = 0;
- ignore[ignore_counter][1] = 0;
- ignore_counter++;
- ignore[ignore_counter][0] = 0;
- ignore[ignore_counter][1] = 1;
- ignore_counter++;
- }
- else
- {
- ignore[ignore_counter][0] = 2;
- ignore[ignore_counter][1] = 0;
- ignore_counter++;
- ignore[ignore_counter][0] = 2;
- ignore[ignore_counter][1] = 1;
- ignore_counter++;
- }
- else if (colinear(screen_axis[1],screen_axis[2]))
- if (length(screen_axis[1]) < length(screen_axis[2]))
- {
- ignore[ignore_counter][0] = 1;
- ignore[ignore_counter][1] = 0;
- ignore_counter++;
- ignore[ignore_counter][0] = 1;
- ignore[ignore_counter][1] = 1;
- ignore_counter++;
- }
- else
- {
- ignore[ignore_counter][0] = 2;
- ignore[ignore_counter][1] = 0;
- ignore_counter++;
- ignore[ignore_counter][0] = 2;
- ignore[ignore_counter][1] = 1;
- ignore_counter++;
- }
- }
-
-
-
- if ((plane == NONE) &&
- (((! line_constrain) && (! plane_constrain)) ||
- ((line_constrain || plane_constrain) && (constraint_ok))))
- {
-
- find_close(
- mouse,screen_motion_point,screen_axis,between,ignore,ignore_counter);
-
- if (! at_edge)
- {
- if ((between[0][0] != 0) && (between[1][0] != 0))
- plane = YZ;
- else if ((between[0][0] != 1) && (between[1][0] != 1))
- plane = XZ;
- else if ((between[0][0] != 2) && (between[1][0] != 2))
- plane = XY;
- }
- else
- {
- edge = between[0][0];
- plane = EDGE_PICKED;
- }
- }
-
- /* Compute where the projected mouse position is */
-
- if ((! at_edge)&&(plane == YZ))
- {
- /* Motion in Y-Z plane, X constant
- Find where line hits the x=0 plane
- As always, y = mx + b */
- dx = p2[0] - p1[0];
-
- if (dx != 0.0)
- {
- dy = p2[1] - p1[1];
- dz = p2[2] - p1[2];
-
- y_slope = dy/dx;
- y_int = p2[1] - y_slope*p2[0]; /* at x = 0 */
- y_proj = y_slope*origin[0] + y_int;
-
- z_slope = dz/dx;
- z_int = p2[2] - z_slope*p2[0];
- z_proj = z_slope*origin[0] + z_int;
- }
- else
- {
- y_proj = p2[1];
- z_proj = p2[2];
- }
-
- if ((! line_constrain) || (line_constrain && between[0][0] == 1) ||
- plane_constrain)
- if (y_proj <= limit[1][0])
- origin[1] = limit[1][0];
- else if (y_proj >= limit[1][1])
- origin[1] = limit[1][1];
- else
- origin[1] = y_proj;
-
- if ((! line_constrain) || (line_constrain && between[0][0] == 2) ||
- plane_constrain)
- if (z_proj <= limit[2][0])
- origin[2] = limit[2][0];
- else if (z_proj >= limit[2][1])
- origin[2] = limit[2][1];
- else
- origin[2] = z_proj;
- }
- else if ((! at_edge)&&(plane == XZ))
- {
- /* Motion in X-Z plane, Y constant */
-
- dy = p2[1] - p1[1];
-
- if (dy != 0.0)
- {
- dx = p2[0] - p1[0];
- dz = p2[2] - p1[2];
-
- x_slope = dx/dy;
- x_int = p2[0] - x_slope*p2[1]; /* at y = 0 */
- x_proj = x_slope*origin[1] + x_int;
-
- z_slope = dz/dy;
- z_int = p2[2] - z_slope*p2[1];
- z_proj = z_slope*origin[1] + z_int;
- }
- else
- {
- x_proj = p2[0];
- z_proj = p2[2];
- }
-
- if ((! line_constrain) || (line_constrain && between[0][0] == 0) ||
- plane_constrain)
- if (x_proj <= limit[0][0])
- origin[0] = limit[0][0];
- else if (x_proj >= limit[0][1])
- origin[0] = limit[0][1];
- else
- origin[0] = x_proj;
-
- if ((! line_constrain) || (line_constrain && between[0][0] == 2) ||
- plane_constrain)
- if (z_proj <= limit[2][0])
- origin[2] = limit[2][0];
- else if (z_proj >= limit[2][1])
- origin[2] = limit[2][1];
- else
- origin[2] = z_proj;
-
- }
- else if ((! at_edge)&&(plane == XY))
- {
- /* Motion in X-Y plane, Z constant */
-
- dz = p2[2] - p1[2];
-
- if (dz != 0.0)
- {
- dx = p2[0] - p1[0];
- dy = p2[1] - p1[1];
-
- x_slope = dx/dz;
- x_int = p2[0] - x_slope*p2[2]; /* at z = 0 */
- x_proj = x_slope*origin[2] + x_int;
-
- y_slope = dy/dz;
- y_int = p2[1] - y_slope*p2[2];
- y_proj = y_slope*origin[2] + y_int;
- }
- else
- {
- x_proj = p2[0];
- y_proj = p2[1];
- }
-
- if ((! line_constrain) || (line_constrain && between[0][0] == 0) ||
- plane_constrain)
- if (x_proj <= limit[0][0])
- origin[0] = limit[0][0];
- else if (x_proj >= limit[0][1])
- origin[0] = limit[0][1];
- else
- origin[0] = x_proj;
-
- if ((! line_constrain) || (line_constrain && between[0][0] == 1) ||
- plane_constrain)
- if (y_proj <= limit[1][0])
- origin[1] = limit[1][0];
- else if (y_proj >= limit[1][1])
- origin[1] = limit[1][1];
- else
- origin[1] = y_proj;
- }
- else if (edge == X)
- {
- float cos_angle,base,hyp,slength,q1[3],q2[3];
- Scoord sdx,sdy,newx,newy;
-
- cos_angle=cos_angle_between(screen_axis[0][0],screen_axis[0][1],mouse);
-
- hyp = dist(screen_axis[0][0],mouse);
- base = hyp * cos_angle;
-
- sdx = screen_axis[0][1][0] - screen_axis[0][0][0];
- sdy = screen_axis[0][1][1] - screen_axis[0][0][1];
- slength = fsqrt((float)(sdx*sdx + sdy*sdy));
-
- newx = (Scoord) ( (float)screen_axis[0][0][0] +
- ((float)(screen_axis[0][1][0] - screen_axis[0][0][0]))*(base/slength));
-
- newy = (Scoord) ( (float)screen_axis[0][0][1] +
- ((float)(screen_axis[0][1][1] - screen_axis[0][0][1]))*(base/slength));
-
- mapw(vobj, newx-origin_x, newy-origin_y,
- &q1[0], &q1[1], &q1[2], &q2[0], &q2[1], &q2[2]);
-
- /* in XY plane... */
-
- dz = q2[2] - q1[2];
-
- if (dz != 0.0)
- {
- dx = q2[0] - q1[0];
- dy = q2[1] - q1[1];
-
- x_slope = dx/dz;
- x_int = q2[0] - x_slope*q2[2]; /* at z = 0 */
- x_proj = x_slope*origin[2] + x_int;
-
- y_slope = dy/dz;
- y_int = q2[1] - y_slope*q2[2];
- y_proj = y_slope*origin[2] + y_int;
- }
- else
- {
- x_proj = q2[0];
- y_proj = q2[1];
- }
-
- /* in XZ plane... */
-
- dy = q2[1] - q1[1];
-
- if (dy != 0.0)
- {
- dx = q2[0] - q1[0];
- dz = q2[2] - q1[2];
-
- x_slope = dx/dy;
- x_int = q2[0] - x_slope*q2[1]; /* at y = 0 */
- x_proj2 = x_slope*origin[1] + x_int;
-
- z_slope = dz/dy;
- z_int = q2[2] - z_slope*q2[1];
- z_proj = z_slope*origin[1] + z_int;
- }
- else
- {
- x_proj2 = q2[0];
- z_proj = q2[2];
- }
-
-
- origin[0] = x_proj - ((y_proj - origin[1])*(x_proj -
- x_proj2)/(y_proj-z_proj));
-
-
- if (origin[0] < limit[0][0])
- origin[0] = limit[0][0];
- else if (origin[0] > limit[0][1])
- origin[0] = limit[0][1];
-
-
-
- }
- else if (edge == Y)
- {
- float cos_angle,base,hyp,slength,q1[3],q2[3];
- Scoord sdx,sdy,newx,newy;
-
- cos_angle=cos_angle_between(screen_axis[1][0],screen_axis[1][1],mouse);
-
- hyp = dist(screen_axis[1][0],mouse);
- base = hyp * cos_angle;
-
- sdx = screen_axis[1][1][0] - screen_axis[1][0][0];
- sdy = screen_axis[1][1][1] - screen_axis[1][0][1];
- slength = fsqrt((float)(sdx*sdx + sdy*sdy));
-
- newx = (Scoord) ( (float)screen_axis[1][0][0] +
- ((float)(screen_axis[1][1][0] - screen_axis[1][0][0]))*(base/slength));
-
- newy = (Scoord) ( (float)screen_axis[1][0][1] +
- ((float)(screen_axis[1][1][1] - screen_axis[1][0][1]))*(base/slength));
-
- mapw(vobj, newx-origin_x, newy-origin_y,
- &q1[0], &q1[1], &q1[2], &q2[0], &q2[1], &q2[2]);
-
- /* in XY plane... */
-
- dz = q2[2] - q1[2];
-
- if (dz != 0.0)
- {
- dx = q2[0] - q1[0];
- dy = q2[1] - q1[1];
-
- x_slope = dx/dz;
- x_int = q2[0] - x_slope*q2[2]; /* at z = 0 */
- x_proj = x_slope*origin[2] + x_int;
-
- y_slope = dy/dz;
- y_int = q2[1] - y_slope*q2[2];
- y_proj = y_slope*origin[2] + y_int;
- }
- else
- {
- x_proj = q2[0];
- y_proj = q2[1];
- }
-
- /* in YZ plane... */
- dx = q2[0] - q1[0];
-
- if (dx != 0.0)
- {
- dy = q2[1] - q1[1];
- dz = q2[2] - q1[2];
-
- y_slope = dy/dx;
- y_int = q2[1] - y_slope*q2[0]; /* at x = 0 */
- y_proj2 = y_slope*origin[0] + y_int;
-
- z_slope = dz/dx;
- z_int = q2[2] - z_slope*q2[0];
- z_proj = z_slope*origin[0] + z_int;
- }
- else
- {
- y_proj2 = q2[1];
- z_proj = q2[2];
- }
-
-
- origin[1] = y_proj2 - ((z_proj - origin[0])*(y_proj2 -
- y_proj)/(z_proj-x_proj));
-
- if (origin[1] < limit[1][0])
- origin[1] = limit[1][0];
- else if (origin[1] > limit[1][1])
- origin[1] = limit[1][1];
- }
- else if (edge == Z)
- {
- float cos_angle,base,hyp,slength,q1[3],q2[3];
- Scoord sdx,sdy,newx,newy;
-
- cos_angle=cos_angle_between(screen_axis[2][0],screen_axis[2][1],mouse);
-
- hyp = dist(screen_axis[2][0],mouse);
- base = hyp * cos_angle;
-
- sdx = screen_axis[2][1][0] - screen_axis[2][0][0];
- sdy = screen_axis[2][1][1] - screen_axis[2][0][1];
- slength = fsqrt((float)(sdx*sdx + sdy*sdy));
-
- newx = (Scoord) ( (float)screen_axis[2][0][0] +
- ((float)(screen_axis[2][1][0] - screen_axis[2][0][0]))*(base/slength));
-
- newy = (Scoord) ( (float)screen_axis[2][0][1] +
- ((float)(screen_axis[2][1][1] - screen_axis[2][0][1]))*(base/slength));
-
- mapw(vobj, newx-origin_x, newy-origin_y,
- &q1[0], &q1[1], &q1[2], &q2[0], &q2[1], &q2[2]);
-
- /* in XZ plane... */
-
- dy = q2[1] - q1[1];
-
- if (dy != 0.0)
- {
- dx = q2[0] - q1[0];
- dz = q2[2] - q1[2];
-
- x_slope = dx/dy;
- x_int = q2[0] - x_slope*q2[1]; /* at y = 0 */
- x_proj = x_slope*origin[1] + x_int;
-
- z_slope = dz/dy;
- z_int = q2[2] - z_slope*q2[1];
- z_proj = z_slope*origin[1] + z_int;
- }
- else
- {
- x_proj = q2[0];
- z_proj = q2[2];
- }
-
- /* in YZ plane... */
- dx = q2[0] - q1[0];
-
- if (dx != 0.0)
- {
- dy = q2[1] - q1[1];
- dz = q2[2] - q1[2];
-
- y_slope = dy/dx;
- y_int = q2[1] - y_slope*q2[0]; /* at x = 0 */
- y_proj = y_slope*origin[0] + y_int;
-
- z_slope = dz/dx;
- z_int = q2[2] - z_slope*q2[0];
- z_proj2 = z_slope*origin[0] + z_int;
- }
- else
- {
- y_proj = q2[1];
- z_proj2 = q2[2];
- }
-
-
- origin[2] = z_proj2 - ((x_proj - origin[1])*(z_proj2 -
- z_proj)/(x_proj-y_proj));
-
- if (origin[2] < limit[2][0])
- origin[2] = limit[2][0];
- else if (origin[2] > limit[2][1])
- origin[2] = limit[2][1];
-
-
- }
-
- if (old_mmode != MSINGLE);
- {
- mmode(MPROJECTION);
- loadmatrix(old_projection);
- mmode(old_mmode);
- }
-
- if (plane_constrain)
- switch (plane)
- {
- case YZ: constraint_return = SP_YZ_PLANE; break;
- case XZ: constraint_return = SP_XZ_PLANE; break;
- case XY: constraint_return = SP_XY_PLANE; break;
- }
- else if (line_constrain)
- switch (plane)
- {
- case YZ:
- if (between[0][0] == 2)
- constraint_return = SP_Z_AXIS;
- else
- constraint_return = SP_Y_AXIS;
- break;
- case XZ:
- if (between[0][0] == 2)
- constraint_return = SP_Z_AXIS;
- else
- constraint_return = SP_X_AXIS;
- break;
- case XY:
- if (between[0][0] == 1)
- constraint_return = SP_Y_AXIS;
- else
- constraint_return = SP_X_AXIS;
- break;
- }
- return constraint_return;
- }
-
-
- /* In variable between, returns which two axis the mouse position is
- * between. There are six possible axes, pos and neg for each of x,y,z.
- * The closest axis to the mouse position will be in between[0], and
- * the next closest will be in between[1].
- *
- * if ignore is set to 0,1 or 2, that axis will be ignore.
- *
- * Example: if
- * between[0][0] = 1, between[0][1] = 0
- * between[1][0] = 2, between[1][1] = 1
- *
- * means that the mouse is between axis 1, endpoint 0 and axis 2, endpoint 1.
- * Translated, the mouse is between the negative Y and positive Z axes,
- * closer to Y.
- */
- static void find_close(
- Scoord mouse[2],
- Scoord center[2],
- Scoord screen_axis[3][2][2],
- short between[2][2],
- int ignore[3][2],
- int ignore_counter)
- {
- short i, j, k;
- float distance,max1,max2;
-
- max1 = max2 = -2.0; /* nothing will ever be less than -1.0 */
-
- /* find distance from mouse vector to the six axes */
- for(i=0;i<3;i++)
- for(j=0;j<2;j++)
- {
- distance = 0.0;
-
- for (k=0; k<ignore_counter; k++)
- if ((i == ignore[k][0]) && (j == ignore[k][1]))
- distance = -2.0;
-
- if (distance == 0.0)
- distance = find_distance(center, mouse, screen_axis[i][j] );
-
- if (distance > max1)
- {
- between[1][0] = between[0][0];
- between[1][1] = between[0][1];
-
- between[0][0] = i;
- between[0][1] = j;
-
- max2 = max1;
- max1 = distance;
- }
- else if (distance > max2)
- {
- between[1][0] = i;
- between[1][1] = j;
-
- max2 = distance;
- }
-
- }
- }
-
-
- /* Returns the length of the axis. */
- static int length(Scoord axis[2][2])
- {
- int dx,dy;
-
- dx = axis[1][0] - axis[0][0];
- dy = axis[1][1] - axis[0][1];
-
- return ((int)fsqrt((float)(dx*dx + dy*dy)));
- }
-
-
-
-
- /* Finds the "distance" between the two vectors from center to p1, and
- * center to p2. Actually returns the dot product, normalized 0.0 to 1.0.
- */
- static float find_distance(Scoord center[2], Scoord p1[2], Scoord p2[2])
- {
- float result,v1[2],v2[2],n1,n2;
-
- v1[0] = (float)p1[0] - (float)center[0];
- v1[1] = (float)p1[1] - (float)center[1];
-
- v2[0] = (float)p2[0] - (float)center[0];
- v2[1] = (float)p2[1] - (float)center[1];
-
- n1 = fsqrt(v1[0]*v1[0] + v1[1]*v1[1]);
- n2 = fsqrt(v2[0]*v2[0] + v2[1]*v2[1]);
-
- result = (v1[0]/n1)*(v2[0]/n2) + (v1[1]/n1)*(v2[1]/n2);
-
- return(result);
- }
-
- /*
- Returns the cosine of angle between the vectors P1 and P2 with common start
- point center
- */
- static float cos_angle_between(Scoord center[2], Scoord p1[2], Scoord p2[2])
- {
- float v1[2],v2[2],n1,n2;
-
- v1[0] = (float)p1[0] - (float)center[0];
- v1[1] = (float)p1[1] - (float)center[1];
-
- v2[0] = (float)p2[0] - (float)center[0];
- v2[1] = (float)p2[1] - (float)center[1];
-
- n1 = fsqrt(v1[0]*v1[0] + v1[1]*v1[1]);
- n2 = fsqrt(v2[0]*v2[0] + v2[1]*v2[1]);
-
- return (v1[0]*v2[0] + v1[1]*v2[1])/(n1*n2);
- }
-
-
- static float dist(Scoord p1[2], Scoord p2[2])
- {
- float result,v1[2];
-
- v1[0] = (float)p2[0] - (float)p1[0];
- v1[1] = (float)p2[1] - (float)p1[1];
-
- return fsqrt(v1[0]*v1[0] + v1[1]*v1[1]);
- }
-
-
-
- /*
- * Takes a world coordinate (x,y,z) and pumps it through tranformation
- * matrix M, returning the screen coordinate in result.
- *
- * Note: One could use feedback to do this, but it turns out to be
- * faster to do it manually.
- */
- static void transform_point(Coord *p, Matrix M, Scoord *result)
- {
- Coord x,y,z,w,hx,hy;
-
- x = p[0]*M[0][0] + p[1]*M[1][0] + p[2]*M[2][0] + M[3][0];
- y = p[0]*M[0][1] + p[1]*M[1][1] + p[2]*M[2][1] + M[3][1];
- z = p[0]*M[0][2] + p[1]*M[1][2] + p[2]*M[2][2] + M[3][2];
- w = p[0]*M[0][3] + p[1]*M[1][3] + p[2]*M[2][3] + M[3][3];
-
- /* Homogeneous coords b/w -1 and 1 */
- hx = x/w;
- hy = y/w;
-
- result[0] = (Scoord)((1.0 + hx)*(Coord)size_x/2.0) + origin_x;
- result[1] = (Scoord)((1.0 + hy)*(Coord)size_y/2.0) + origin_y;
- }
-
-
- /*
- * Returns TRUE if the two axes are colinear within COLINEAR_THRESHOLD
- * pixels.
- *
- * Finds the distance from endpoint of one two line of other.
- * Taken from handbook of mathematical tables... p. 159
- */
- static Boolean colinear(Scoord a1[2][2], Scoord a2[2][2])
- {
- float dx,dy,m,b,A,B,C,dist1,dist2;
-
- dx = (float)(a1[0][0] - a1[1][0]);
-
- if (dx == 0.0)
- dx = 0.0001;
-
- dy = (float)(a1[0][1] - a1[1][1]);
-
- m = dy/dx; /* slope */
- b = (float)a1[0][1] - m*(float)a1[0][0]; /* y intercept */
-
- A = -m;
- B = 1.0;
- C = -b;
-
- dist1 = (A*(float)a2[0][0] + B*(float)a2[0][1] + C)/
- fsqrt(A*A + B*B);
-
- dist2 = (A*(float)a2[1][0] + B*(float)a2[1][1] + C)/
- fsqrt(A*A + B*B);
-
- if ((fabs(dist1) < (float)SP_COLINEAR_THRESHOLD) && (fabs(dist2) < (float)SP_COLINEAR_THRESHOLD))
- return TRUE;
- else
- return FALSE;
- }
-
-
-
-